package com.icim.csot.exporter.job;

import java.io.File;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Resource;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.icim.core.pojo.FtpConfigure;
import com.icim.core.service.IAlarmSenderService;
import com.icim.core.service.IFtpService;
import com.icim.csot.exporter.tentity.CsotHistoryTEntity;
import com.icim.dao.HisRetPrdInfoDao;
import com.icim.dao.RetCusPrdIndtDao;
import com.icim.dao.RetCusSoDao;
import com.icim.dao.RetPrdInfoDao;
import com.icim.dao.RetWoDao;
import com.icim.def.ComDef;
import com.icim.entity.His_ret_prd_info;
import com.icim.entity.Ret_cus_prd_indt;
import com.icim.entity.Ret_cus_so;
import com.icim.entity.Ret_prd_info;
import com.icim.entity.Ret_wo;
import com.icim.util.GzCompressUtil;
import com.icim.util.TxtFileUtil;
import com.icim.util.TimeUtil;
import static com.icim.def.ComDef.*;

public class CsotExportHistoryJob {

    private final static Logger logger = LoggerFactory.getLogger(CsotExportHistoryJob.class);

    private Timestamp beginTimestamp;
    private Timestamp endTimestamp;
    private Timestamp indexTimestamp;
    private String strBeginTime;
    private String strEndTime;
    private FtpConfigure ftpConfigure;
    private int endTimeMak;

    @Resource
    private RetWoDao retWoDao;

    @Resource
    private RetPrdInfoDao retPrdInfoDao;
    @Resource
    private RetCusSoDao retCusSoDao;
    @Resource
    private RetCusPrdIndtDao retCusPrdIndtDao;
    @Resource
    private HisRetPrdInfoDao hisRetPrdInfoDao;

    private IFtpService ftpService;
    
    @Resource
    private IAlarmSenderService alarmSenderService;

    public void subMainProc() {
        logger.info("export history system running .....");

        /**
         * get time period : begin time & end time
         */
        try {
            getTimePeriod();
			subMainProc2();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			String errorMsg="his数据回传失败，开始时间："+beginTimestamp+"  结束时间："+endTimestamp+"\n"+"失败原因："+e.getMessage();
        	alarmSenderService.sendAlarm1("007",errorMsg);
		}

        logger.info("export history successfull ......");
    }

    public void subMainProc2() throws Exception {
        /**
         * get all work order by custom id
         */
        List<Ret_wo> woList = findAllWorkerOrder();

        /**
         * query table HIS_RET_PRD_INFO by custom_id & time period
         */

        long time = beginTimestamp.getTime();
        DateTime beginDt = new DateTime(time);
        DateTime indexDt = beginDt.plusHours(-2);
        indexTimestamp = new Timestamp(indexDt.getMillis());
        
//        List<His_ret_prd_info> sheetHistories = hisRetPrdInfoDao.findSheets(woList, TimeUtil.getDoubleTimeByTimestamp(beginTimestamp), TimeUtil.getDoubleTimeByTimestamp(endTimestamp),indexTimestamp);
        List<His_ret_prd_info> sheetHistories = hisRetPrdInfoDao.findSheets(woList, beginTimestamp, endTimestamp);
        logger.info("find {} records ....", sheetHistories.size());

        if (sheetHistories.size() == 0) {
            return;
        }
        /**
         * distinct sheet ids then add to SET
         */
        // Map<String,His_ret_prd_info> sheetHistoryMap = new
        // HashMap<String,His_ret_prd_info>();

        Set<String> sheetSet = new HashSet<String>();
        Set<String> soSet = new HashSet<String>();

        for (His_ret_prd_info hisRetPrdInfo : sheetHistories) {
            // sheetHistoryMap.put(hisRetPrdInfo.getPrd_seq_id(),
            // hisRetPrdInfo);
            sheetSet.add(hisRetPrdInfo.getPrd_seq_id());
            soSet.add(hisRetPrdInfo.getSo_id_fk());
        }

        /*
         * get records in table RET_PRD_INFO,RET_CUS_PRD_INDT,RET_CUS_SO, then
         * put them into map;
         */

        Map<String, Ret_cus_prd_indt> retCusPrdIndtMap = new HashMap<String, Ret_cus_prd_indt>();
        List<Ret_cus_prd_indt> retCusPrdIndtList = retCusPrdIndtDao.findPrdIndtList(sheetSet);

        logger.info("searching table ret_cus_prd_indt, find " + retCusPrdIndtList.size() + " records");
        for (Ret_cus_prd_indt retCusPrdIndt : retCusPrdIndtList) {
            retCusPrdIndtMap.put(retCusPrdIndt.getCellBlockId(), retCusPrdIndt);
        }

        Map<String, Ret_cus_so> retCusSoMap = new HashMap<String, Ret_cus_so>();
       
        List<Ret_cus_so> retCusSoList = retCusSoDao.findRetCusSoList(soSet);
        for (Ret_cus_so retCusSo : retCusSoList) {
            retCusSoMap.put(retCusSo.getIcimSoId(), retCusSo);
        }
        
        sheetHistories = filterHistory(sheetHistories);

        /**
         * loop sheets make tFile
         */
        List<CsotHistoryTEntity> tEntityList = new ArrayList<CsotHistoryTEntity>();
        for (His_ret_prd_info hisRetPrdInfo : sheetHistories) {
            CsotHistoryTEntity tEntity = new CsotHistoryTEntity();
            CsotHistoryTEntity tEntity1 = null;
            String sheetId = hisRetPrdInfo.getPrd_seq_id();
            tEntity.setFACTORY(CSOT_FACTORY_NAME);
            tEntity.setPANEL_ID(sheetId);
            tEntity.setCSOT_PANEL_ID(sheetId);
            tEntity.setPALLET_ID(checkIsNull(hisRetPrdInfo.getPallet_id()));
            tEntity.setBOX_ID(checkIsNull(hisRetPrdInfo.getShip_box_id_fk()));
            tEntity.setSOURCE_PALLET_ID(getRetCusIndtMap(retCusPrdIndtMap, sheetId, "mtrlPalletNo"));
            
          
            tEntity.setBLOCK_STATUS(getRetShtStat(hisRetPrdInfo));
            
            tEntity.setSOURCE_BOX_ID(getRetCusIndtMap(retCusPrdIndtMap, sheetId, "mtrlBoxId"));
            /*tEntity.setEVENT_TIMEKEY(getEventTimeKey(hisRetPrdInfo.getSta_time_d()));
            tEntity.setEVENT_TIME(getEventTime(hisRetPrdInfo.getSta_time_d()));*/
            tEntity.setEVENT_TIMEKEY(getEventTimeKeyByTimestamp(hisRetPrdInfo.getEvt_timestamp()));
            tEntity.setEVENT_TIME(getEventTimeByTimestamp(hisRetPrdInfo.getEvt_timestamp()));
            
            
            tEntity.setEVENT_NAME(getRetEvtCate(hisRetPrdInfo));

            
            
            tEntity.setEVENT_USER_ID(checkIsNull(hisRetPrdInfo.getEvt_usr()));
            tEntity.setEVENT_COMMENT(checkIsNull(hisRetPrdInfo.getDs_recipe_id()));
            tEntity.setPO_TYPE(getRetCusSoMap(retCusSoMap, hisRetPrdInfo.getSo_id_fk(), "cusSoCate"));
            tEntity.setPO_ID(getRetCusSoMap(retCusSoMap, hisRetPrdInfo.getSo_id_fk(), "cusSoId"));
            tEntity.setPRODUCT_GROUP("");
            tEntity.setMODEL_NAME("");
            tEntity.setPRODUCT_ID(checkIsNull(hisRetPrdInfo.getMdl_id_fk()));
            tEntity.setOWNER_ID(checkIsNull(hisRetPrdInfo.getGroup_id()));
            tEntity.setPRODUCT_VER("");
            tEntity.setSOURCE_PRODUCT_ID(checkIsNull(hisRetPrdInfo.getMtrl_product_id()));
            tEntity.setCELL_GRADE("OK");
            tEntity.setGRADE(checkIsNull(hisRetPrdInfo.getPrd_grade()));
            
            
            //tEntity.setOPER_CODE(checkIsNull(hisRetPrdInfo.getCr_ope_id_fk()));
            
            tEntity.setOPER_CODE(getWhinRetOpe(hisRetPrdInfo));
            
            
            
            tEntity.setLINE_ID(checkIsNull(hisRetPrdInfo.getLine_id()));
            tEntity.setEQP_ID(checkIsNull(hisRetPrdInfo.getCr_tool_id_fk()));
//            tEntity.setREWORK_CNT("Y".equals(hisRetPrdInfo.getProc_flg()) ? "N" : "Y");
            tEntity.setREWORK_CNT(checkIsNull(hisRetPrdInfo.getRsn_cate1()));
            tEntity.setREASON_CODE_TYPE(getReasonCodeType(hisRetPrdInfo.getPrd_grade()));
            tEntity.setREASON_CODE(getReasonCode(hisRetPrdInfo.getPrd_grade(), hisRetPrdInfo.getRsn_dept1()));
            tEntity.setDEFECT_GROUP("");
            tEntity.setDEFECT_CODE("");
            tEntity.setDEFECT_QTY("");

            tEntity.setABNORMAL_FLAG(getRetCusIndtMap(retCusPrdIndtMap, sheetId, "slimFlg"));
            tEntity.setSLIM_FLAG(checkIsNull(hisRetPrdInfo.getPrd_grade()));

            tEntityList.add(tEntity);
            if("WHOT".equals(hisRetPrdInfo.getEvt_cate())){
            	tEntity1=new CsotHistoryTEntity();

            	tEntity1.setFACTORY(CSOT_FACTORY_NAME);
            	tEntity1.setPANEL_ID(sheetId);
            	tEntity1.setCSOT_PANEL_ID(sheetId);
            	tEntity1.setPALLET_ID(checkIsNull(hisRetPrdInfo.getPallet_id()));
            	tEntity1.setBOX_ID(checkIsNull(hisRetPrdInfo.getShip_box_id_fk()));
            	tEntity1.setSOURCE_PALLET_ID(getRetCusIndtMap(retCusPrdIndtMap, sheetId, "mtrlPalletNo"));
                tEntity1.setBLOCK_STATUS("COMP");
                tEntity1.setSOURCE_BOX_ID(getRetCusIndtMap(retCusPrdIndtMap, sheetId, "mtrlBoxId"));
               /* tEntity1.setEVENT_TIMEKEY(getEventTimeKey(hisRetPrdInfo.getSta_time_d()));
                tEntity1.setEVENT_TIME(getEventTime(hisRetPrdInfo.getSta_time_d()));*/
                
                tEntity1.setEVENT_TIMEKEY(getEventTimeKeyByTimestamp(hisRetPrdInfo.getEvt_timestamp()));
                tEntity1.setEVENT_TIME(getEventTimeByTimestamp(hisRetPrdInfo.getEvt_timestamp()));
                
                tEntity1.setEVENT_NAME(getRetEvtCate(hisRetPrdInfo));
                tEntity1.setEVENT_USER_ID(checkIsNull(hisRetPrdInfo.getEvt_usr()));
                tEntity1.setEVENT_COMMENT(checkIsNull(hisRetPrdInfo.getDs_recipe_id()));
                tEntity1.setPO_TYPE(getRetCusSoMap(retCusSoMap, hisRetPrdInfo.getSo_id_fk(), "cusSoCate"));
                tEntity1.setPO_ID(getRetCusSoMap(retCusSoMap, hisRetPrdInfo.getSo_id_fk(), "cusSoId"));
                tEntity1.setPRODUCT_GROUP("");
                tEntity1.setMODEL_NAME("");
                tEntity1.setPRODUCT_ID(checkIsNull(hisRetPrdInfo.getMdl_id_fk()));
                tEntity1.setOWNER_ID(checkIsNull(hisRetPrdInfo.getGroup_id()));
                tEntity1.setPRODUCT_VER("");
                tEntity1.setSOURCE_PRODUCT_ID(checkIsNull(hisRetPrdInfo.getMtrl_product_id()));
                tEntity1.setCELL_GRADE("OK");
                tEntity1.setGRADE(checkIsNull(hisRetPrdInfo.getPrd_grade()));          
                tEntity1.setOPER_CODE(getWhinRetOpe(hisRetPrdInfo));
                tEntity1.setLINE_ID(checkIsNull(hisRetPrdInfo.getLine_id()));
                tEntity1.setEQP_ID(checkIsNull(hisRetPrdInfo.getCr_tool_id_fk()));
                tEntity1.setREWORK_CNT(checkIsNull(hisRetPrdInfo.getRsn_cate1()));
                tEntity1.setREASON_CODE_TYPE(getReasonCodeType(hisRetPrdInfo.getPrd_grade()));
                tEntity1.setREASON_CODE(getReasonCode(hisRetPrdInfo.getPrd_grade(), hisRetPrdInfo.getRsn_dept1()));
                tEntity1.setDEFECT_GROUP("");
                tEntity1.setDEFECT_CODE("");
                tEntity1.setDEFECT_QTY("");
                tEntity1.setABNORMAL_FLAG(getRetCusIndtMap(retCusPrdIndtMap, sheetId, "slimFlg"));
                tEntity1.setSLIM_FLAG(checkIsNull(hisRetPrdInfo.getPrd_grade()));	
                tEntityList.add(tEntity1);
            }
        }

        String fileName = getFtpConfigure().getLocalHistoryGzPath().trim() + "/BLOCK_HIST_" + strEndTime + ".txt";
        try {
            TxtFileUtil.entity2Txt(tEntityList, fileName, strBeginTime, strEndTime);
            logger.info("building tFile process [" + fileName + "]");
            GzCompressUtil.compress(new File(fileName));
            // 上传ftp
            logger.info("compress file process ....");
            String gzFileName = fileName + ".gz";
            File gzFile = new File(gzFileName);
            ftpService.connect();
            ftpService.uploadFile(gzFile, getFtpConfigure().getFtpHistoryExportPath());
            ftpService.disconnectFtp();
        } catch (Exception e) {
            logger.error(e.toString());
            throw e;
        }

    }

    private List<His_ret_prd_info> filterHistory(List<His_ret_prd_info> sheetHistories) {
    	List<His_ret_prd_info> fiterHistoryList = new ArrayList<His_ret_prd_info>();
    	
    	
    	Map<String ,His_ret_prd_info> stbiHistoryMap =new HashMap<String,His_ret_prd_info>();
    	
    	for (His_ret_prd_info hisRetPrdInfo : sheetHistories) {
    		
    		String prdSeqId = hisRetPrdInfo.getPrd_seq_id();
    		//filter the newest STBI history to HashMap
    		if("STBI".equals(hisRetPrdInfo.getEvt_cate())){
    			His_ret_prd_info stbiHisRetPrdInfo = stbiHistoryMap.get(prdSeqId);
    			if(stbiHisRetPrdInfo ==null){
    				stbiHistoryMap.put(prdSeqId,hisRetPrdInfo);
    			}else{
    				if(hisRetPrdInfo.getEvt_timestamp().after(stbiHisRetPrdInfo.getEvt_timestamp())){
    					stbiHistoryMap.put(prdSeqId,hisRetPrdInfo);
    				}
    			}
    			
    		}else{
    			fiterHistoryList.add(hisRetPrdInfo);
    		}
		}
    	
    	//add the newest STBI history
    	Set<Entry<String, His_ret_prd_info>> stbiHistoryEntrySet = stbiHistoryMap.entrySet();
    	for (Entry<String, His_ret_prd_info> stbiHistoryEntry : stbiHistoryEntrySet) {
    		fiterHistoryList.add(stbiHistoryEntry.getValue());
		}
    	
    	
    	return fiterHistoryList;
	}
    
    public String getWhinRetOpe(His_ret_prd_info hisRetPrdInfo){
    	if("WHIN".equals(hisRetPrdInfo.getEvt_cate())||"WHOT".equals(hisRetPrdInfo.getEvt_cate())){
        	return "CPCK";
        }else{
        	return checkIsNull(hisRetPrdInfo.getCr_ope_id_fk());
        }	
    	
    }
    
    public String getRetShtStat(His_ret_prd_info hisRetPrdInfo){
    	 if("WHIN".equals(hisRetPrdInfo.getEvt_cate())){
         	 return "RUN";
         }else if("WHOT".equals(hisRetPrdInfo.getEvt_cate())){
         	  return "WAIT";
         }else{
        	 return getBlockStatus(hisRetPrdInfo.getPrd_stat());
         }
    }
    
    public String getRetEvtCate(His_ret_prd_info hisRetPrdInfo){
    	if("WHIN".equals(hisRetPrdInfo.getEvt_cate())){
        	return "LGON";
        }else if("WHOT".equals(hisRetPrdInfo.getEvt_cate())){
        	return "LGOF";
        }else{
        	return checkIsNull(hisRetPrdInfo.getEvt_cate());
        }	
    }

	private String checkIsNull(String str) {
        return str == null ? "" : str;
    }

    private String getRetCusIndtMap(Map<String, Ret_cus_prd_indt> retCusPrdIndtMap, String sheetId, String column) {
        if (!retCusPrdIndtMap.containsKey(sheetId)) {
            return "";
        }
        String value = null;
        if ("mtrlPalletNo".equals(column)) {
            value = retCusPrdIndtMap.get(sheetId).getMtrlPalletNo();
        } else if ("slimFlg".equals(column)) {
            value = retCusPrdIndtMap.get(sheetId).getSlimFlg();
        } else if ("mtrlBoxId".equals(column)) {
            value = retCusPrdIndtMap.get(sheetId).getMtrlBoxId();
        }
        return value == null ? "" : value;
    }

    private String getRetCusSoMap(Map<String, Ret_cus_so> retCusSoMap, String soId, String column) {
        if (!retCusSoMap.containsKey(soId)) {
            return "";
        }
        String value = "";
        if ("cusSoCate".equals(column)) {
            value = retCusSoMap.get(soId).getCusSoCate();
        } else if ("cusSoId".equals(column)) {
            value = retCusSoMap.get(soId).getCusSoId();
        }
        return value == null ? "" : value;
    }

    private String getReasonCode(String prdGrade, String rsnDept1) {
        if ("SC".equals(prdGrade) && "I".equals(rsnDept1)) {
            return "sCELL";
        } else if ("SC".equals(prdGrade) && "P".equals(rsnDept1)) {
            return "sOEM";
        } else if ("RM".equals(prdGrade) && "I".equals(rsnDept1)) {
            return "rCELL";
        } else if ("RM".equals(prdGrade) && "P".equals(rsnDept1)) {
            return "rOEM";
        }
        return "";
    }

    private String getReasonCodeType(String prdGrade) {
        if ("SC".equals(prdGrade)) {
            return "Scrap";
        } else if ("RM".equals(prdGrade)) {
            return "Remark";
        }
        return "";
    }

    private String getOperCode(His_ret_prd_info hisRetPrdInfo) {
        String prdStat = hisRetPrdInfo.getPrd_stat();
        if ("INPR".equals(prdStat) || "COMP".equals(prdStat) || "SHIP".equals(prdStat) || "SHTC".equals(prdStat)) {
            return hisRetPrdInfo.getCr_ope_id_fk();
        } else {
            return hisRetPrdInfo.getNx_ope_id_fk();
        }
    }

    /**
     * 
     */
    private void getTimePeriod() {
        DateTime dt = new DateTime();

        DateTime endDt = dt.plusMinutes(endTimeMak);
        endTimestamp = new Timestamp(endDt.getMillis());

        DateTime beginDt = endDt.plusHours(-1);
        beginTimestamp = new Timestamp(beginDt.getMillis());
        
        DateTime indexDt = endDt.plusHours(-2);
        indexTimestamp = new Timestamp(indexDt.getMillis());

        
        strEndTime = getTimeFromDateTime(endDt);
        strBeginTime = getTimeFromDateTime(beginDt);

        logger.info("begin time:" + beginTimestamp);
        logger.info("end time :" + endTimestamp);
    }
    
    private String getTimeFromDateTime(DateTime dt) {
               return comInt2String(dt.getYear(), 4) + comInt2String(dt.getMonthOfYear(), 2)
                        + comInt2String(dt.getDayOfMonth(), 2) + comInt2String(dt.getHourOfDay(), 2)
                        + comInt2String(dt.getMinuteOfHour(), 2) + comInt2String(dt.getSecondOfMinute(),2);
    }

    private String getBlockStatus(String prdStat) {
        return "INPR".equals(prdStat) ? "RUN" : prdStat;
    }

    private String getEventTimeKey(Double dTime) {
        return TimeUtil.getMilliTimestampByDblTime(dTime).replace("-", "").replace(":", "").replace(".", "").replace(" ", "");
    }

    private String getEventTime(Double dTime) {
        return TimeUtil.getTimestampByDblTime(dTime).replace("-", "/");
    }
    
    private String getEventTimeKeyByTimestamp(Timestamp timestamp){
    	return  timestamp.toString().replace("-", "").replace(":", "").replace(".", "").replace(" ", "")+"00";
    }
    
    private String getEventTimeByTimestamp(Timestamp timestamp){
    	 String timestampStr=timestamp.toString().replace("-", "/");
    	 return timestampStr.substring(0, timestampStr.length()-2);
    }

    private List<Ret_wo> findAllWorkerOrder() {
        return retWoDao.findWoListByCusId(ComDef.CUS_ID);
    }

    public static void main(String[] args) {
        new CsotExportHistoryJob().getTimePeriod();
    }

    public Timestamp getBeginTimestamp() {
        return beginTimestamp;
    }

    public void setBeginTimestamp(Timestamp beginTimestamp) {
        this.beginTimestamp = beginTimestamp;
    }

    public Timestamp getEndTimestamp() {
        return endTimestamp;
    }

    public void setEndTimestamp(Timestamp endTimestamp) {
        this.endTimestamp = endTimestamp;
    }

    public String getStrBeginTime() {
        return strBeginTime;
    }

    public void setStrBeginTime(String strBeginTime) {
        this.strBeginTime = strBeginTime;
    }

    public String getStrEndTime() {
        return strEndTime;
    }

    public void setStrEndTime(String strEndTime) {
        this.strEndTime = strEndTime;
    }

    public FtpConfigure getFtpConfigure() {
        return ftpConfigure;
    }

    public void setFtpConfigure(FtpConfigure ftpConfigure) {
        this.ftpConfigure = ftpConfigure;
    }

    public String comInt2String(int value, int length) {
        String s = String.valueOf(value);
        if (s.length() > length) {
            throw new RuntimeException("length is too short.");
        } else if (s.length() == length) {
            return s;
        } else {
            char[] cc = new char[length];
            int i = 0;
            for (; i < length - s.length(); i++) {
                cc[i] = '0';
            }
            for (int j = 0; j < s.length(); i++, j++) {
                // System.out.println(i);
                cc[i] = s.charAt(j);
            }
            return new String(cc);
        }
    }

    public IFtpService getFtpService() {
        return ftpService;
    }

    public void setFtpService(IFtpService ftpService) {
        this.ftpService = ftpService;
    }
    public int getEndTimeMak() {
		return endTimeMak;
	}

	public void setEndTimeMak(int endTimeMak) {
		this.endTimeMak = endTimeMak;
	}

    

}
